package cn.jbolt.core.db.dialect;

import cn.jbolt.core.util.JBoltArrayUtil;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.Table;
import com.jfinal.plugin.activerecord.builder.TimestampProcessedModelBuilder;
import com.jfinal.plugin.activerecord.builder.TimestampProcessedRecordBuilder;
import com.jfinal.plugin.activerecord.dialect.Dialect;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class JBoltSqlServerDialect extends Dialect {
	public JBoltSqlServerDialect() {
		this.modelBuilder = TimestampProcessedModelBuilder.me;
		this.recordBuilder = TimestampProcessedRecordBuilder.me;
	}
	@Override
	public String forTableBuilderDoBuild(String tableName) {
		return "select * from [" + tableName + "] where 1 = 2";
	}
	@Override
	public void forModelSave(Table table, Map<String, Object> attrs, StringBuilder sql, List<Object> paras) {
		sql.append("insert into [").append(table.getName()).append("](");
		StringBuilder temp = new StringBuilder(") values(");
		String[] primaryKeys = table.getPrimaryKey();
		for (Entry<String, Object> e : attrs.entrySet()) {
			String colName = e.getKey();
			if (table.hasColumnLabel(colName)) {
				// 如果有主键 并且主键是NULL 就不要设置了
				if (cn.hutool.core.util.ArrayUtil.containsIgnoreCase(primaryKeys, colName) && e.getValue() == null) {
					System.out.println("=========forModelSave  continue");
					continue;
				}
				if (paras.size() > 0) {
					sql.append(", ");
					temp.append(", ");
				}
				sql.append("[").append(colName).append("]");
				temp.append('?');
				paras.add(e.getValue());
			}
		}
		sql.append(temp.toString()).append(")");
	}
	@Override
	public String forModelDeleteById(Table table) {
		String[] pKeys = table.getPrimaryKey();
		StringBuilder sql = new StringBuilder(45);
		sql.append("delete from [");
		sql.append(table.getName());
		sql.append("] where ");
		for (int i = 0; i < pKeys.length; i++) {
			if (i > 0) {
				sql.append(" and ");
			}
			sql.append("[").append(pKeys[i]).append("] = ?");
		}
		return sql.toString();
	}
	@Override
	public void forModelUpdate(Table table, Map<String, Object> attrs, Set<String> modifyFlag, StringBuilder sql,
			List<Object> paras) {
		sql.append("update [").append(table.getName()).append("] set ");
		String[] pKeys = table.getPrimaryKey();
		for (Entry<String, Object> e : attrs.entrySet()) {
			String colName = e.getKey();
			if (modifyFlag.contains(colName) && !isPrimaryKey(colName, pKeys) && table.hasColumnLabel(colName)) {
				if (paras.size() > 0) {
					sql.append(", ");
				}
				sql.append("[").append(colName).append("] = ? ");
				paras.add(e.getValue());
			}
		}
		sql.append(" where ");
		for (int i = 0; i < pKeys.length; i++) {
			if (i > 0) {
				sql.append(" and ");
			}
			sql.append("[").append(pKeys[i]).append("] = ?");
			paras.add(attrs.get(pKeys[i]));
		}
	}
	@Override
	public String forModelFindById(Table table, String columns) {
		StringBuilder sql = new StringBuilder("select ");
		columns = columns.trim();
		if ("*".equals(columns)) {
			sql.append('*');
		} else {
			if (columns.indexOf(",") != -1) {
				String[] columnArray = JBoltArrayUtil.from3(columns, ",");
				if (columnArray == null || columnArray.length == 0) {
					sql.append("*");
				} else {
					int size = columnArray.length;
					if (size == 1) {
						sql.append("[").append(columnArray[0]).append("]");
					} else {
						for (int i = 0; i < size; i++) {
							sql.append("[").append(columnArray[i]).append("]");
							if (i < size - 1) {
								sql.append(",");
							}
						}
					}
				}
			} else {
				sql.append("[").append(columns).append("]");
			}
		}

		sql.append(" from [");
		sql.append(table.getName());
		sql.append("] where ");
		String[] pKeys = table.getPrimaryKey();
		for (int i = 0; i < pKeys.length; i++) {
			if (i > 0) {
				sql.append(" and ");
			}
			sql.append("[").append(pKeys[i]).append("] = ?");
		}
		return sql.toString();
	}
	@Override
	public String forDbFindById(String tableName, String[] pKeys) {
		tableName = tableName.trim();
		trimPrimaryKeys(pKeys);

		StringBuilder sql = new StringBuilder("select * from [").append(tableName).append("] where ");
		for (int i = 0; i < pKeys.length; i++) {
			if (i > 0) {
				sql.append(" and ");
			}
			sql.append("[").append(pKeys[i]).append("] = ?");
		}
		return sql.toString();
	}
	@Override
	public String forDbDeleteById(String tableName, String[] pKeys) {
		tableName = tableName.trim();
		trimPrimaryKeys(pKeys);

		StringBuilder sql = new StringBuilder("delete from [").append(tableName).append("] where ");
		for (int i = 0; i < pKeys.length; i++) {
			if (i > 0) {
				sql.append(" and ");
			}
			sql.append("[").append(pKeys[i]).append("] = ?");
		}
		return sql.toString();
	}
	@Override
	public void forDbSave(String tableName, String[] pKeys, Record record, StringBuilder sql, List<Object> paras) {
		tableName = tableName.trim();
		trimPrimaryKeys(pKeys);

		sql.append("insert into [");
		sql.append(tableName).append("](");
		StringBuilder temp = new StringBuilder();
		temp.append(") values(");

		for (Entry<String, Object> e : record.getColumns().entrySet()) {
			if (paras.size() > 0) {
				sql.append(", ");
				temp.append(", ");
			}
			sql.append("[").append(e.getKey()).append("]");
			temp.append('?');
			paras.add(e.getValue());
		}
		sql.append(temp.toString()).append(')');
	}
	@Override
	public void forDbUpdate(String tableName, String[] pKeys, Object[] ids, Record record, StringBuilder sql,
			List<Object> paras) {
		tableName = tableName.trim();
		trimPrimaryKeys(pKeys);

		sql.append("update [").append(tableName).append("] set ");
		for (Entry<String, Object> e : record.getColumns().entrySet()) {
			String colName = e.getKey();
			if (!isPrimaryKey(colName, pKeys)) {
				if (paras.size() > 0) {
					sql.append(", ");
				}
				sql.append("[").append(colName).append("] = ? ");
				paras.add(e.getValue());
			}
		}
		sql.append(" where ");
		for (int i = 0; i < pKeys.length; i++) {
			if (i > 0) {
				sql.append(" and ");
			}
			sql.append("[").append(pKeys[i]).append("] = ?");
			paras.add(ids[i]);
		}
	}

	/**
	 * sql.replaceFirst("(?i)select", "") 正则中带有 "(?i)" 前缀，指定在匹配时不区分大小写
	 */
	@Override
	public String forPaginate(int pageNumber, int pageSize, StringBuilder findSql) {
		int end = pageNumber * pageSize;
		if (end <= 0) {
			end = pageSize;
		}
		int begin = (pageNumber - 1) * pageSize;
		if (begin < 0) {
			begin = 0;
		}
		StringBuilder ret = new StringBuilder();
		ret.append("SELECT * FROM ( SELECT row_number() over (order by tempcolumn) temprownumber, * FROM ");
		ret.append(" ( SELECT TOP ").append(end).append(" tempcolumn=0,");
		ret.append(findSql.toString().replaceFirst("(?i)select", ""));
		ret.append(")vip)mvp where temprownumber>").append(begin);
		return ret.toString();
	}
	@Override
	public void fillStatement(PreparedStatement pst, List<Object> paras) throws SQLException {
		fillStatementHandleDateType(pst, paras);
	}
	@Override
	public void fillStatement(PreparedStatement pst, Object... paras) throws SQLException {
		fillStatementHandleDateType(pst, paras);
	}

}
